home *** CD-ROM | disk | FTP | other *** search
- /* board.c
- * S.Coffin USWAT 1/93
- *
- * adapted from adrian@u.washington.edu [with significant changes]
- * keeps local copy of board state, dead stone removal, handicaps, etc
- */
-
- #include <stdio.h>
- #include <time.h>
- #include "shared.h"
- #include "filter.h"
-
- extern int drawStone();
- extern int move, currentmove;
- extern int boardchanged, mouseflag;
- extern int beep();
- static int tt;
- void removeStones();
-
- typedef unsigned char boardtype[20][20];
- int prisoners[2], stepprisoners[2];
-
- struct movelist {
- int x, y;
- unsigned char flag;
- };
-
- static struct movelist realmovelist[MAXMOVE], stepmovelist[MAXMOVE];
-
- boardtype board, stepboard;
-
- #define boolean unsigned char
- #define false 0
- #define true 1
-
- #define piece unsigned char
-
- static int boardsize = 19;
-
-
- clearboard( b, pris )
- boardtype b;
- int *pris;
- {
- int i, j;
- pris[0] = pris[1] = 0;
- for (i = 0; i < boardsize; i++)
- for (j = 0; j < boardsize; j++)
- b[i][j] = EMPTY;
- }
-
- clear_stepboard() {
- clearboard( stepboard, stepprisoners );
- }
-
- initboard( size )
- unsigned char size;
- {
- boardsize = size;
- clearboard( board, prisoners );
- clearboard( stepboard, stepprisoners );
- }
-
- unsigned char *stamptime() {
- char *asctime(); /* stuff to get timestamp */
- struct tm *localtime(), *tp;
- struct timeval tv;
- struct timezone tz;
-
- gettimeofday( &tv, &tz ); /* fill in timestamp */
- tp = localtime( (time_t *)&tv.tv_sec );
- return( (unsigned char *)asctime(tp) );
- }
-
- /* save game in sgf format */
- save_game_sgf( s, p1, p2, hcap, type )
- unsigned char *s; /* file name to save to */
- unsigned char *p1, *p2; /* player names */
- int hcap; /* handicap stones or 0 */
- int type; /* save REALMOVES or STEPMOVES */
- {
- FILE *fp;
- int i, x, y;
- unsigned char *str;
- int m;
- struct movelist *ml;
-
- if( type == REALMOVE ) {
- m = move;
- ml = realmovelist;
- }
- else if( type == STEPMOVE ) {
- m = currentmove;
- ml = stepmovelist;
- }
-
- if( (fp = fopen( (char *)s, "a+" )) == NULL ) {
- perror( "savegame" );
- return( 0 );
- }
- fprintf( fp, "(\n;\nPlayerBlack[%s]\nPlayerWhite[%s]\n",
- p2, p1 );
- str = stamptime();
- str[strlen((char *)str)-1] = '\0';
- fprintf( fp, "GaMe[1]\n" );
- fprintf( fp, "VieW[]\n" );
- fprintf( fp, "EVent[]\n" );
- fprintf( fp, "DaTe[%s]\n", str );
- fprintf( fp, "SiZe[%d]\n", boardsize );
- fprintf( fp, "PlaCe[IGS]\n", boardsize );
- if( hcap ) fprintf( fp, "HAndicap[%d]\n", hcap );
- fprintf( fp, "KoMi[??]\n" );
- fprintf( fp, "USer[File created by IGS and xigc]\n" );
-
- if( hcap != 0 ) {
- sgf_hcap( fp, boardsize, hcap );
- i = 1;
- }
- else i = 0;
-
- fprintf( fp, ";\n" );
-
- for( ; i <= m; ++i ) {
- x = ml[i].x + 1;
- y = ml[i].y + 1;
- if( x < 0 ) { /* pass */
- fprintf( fp, "%s[tt]\n;\n", (i%2) ? "White" : "Black" );
- }
- else { /* real move */
- fprintf( fp, "%s[%c%c]\n;\n", (i%2) ? "White" : "Black",
- 'a' + (unsigned char)x - 1,
- 'a' + (unsigned char)(boardsize - y) );
- }
- }
-
- fprintf( fp, ")\n" );
-
- fclose( fp );
- return( 1 );
- }
-
- /* save the moves in a file */
- save_game( s, p1, p2, hcap, type )
- unsigned char *s; /* file name to save to */
- unsigned char *p1, *p2; /* player names */
- int hcap; /* handicap stones or 0 */
- int type; /* save REALMOVE or STEPMOVE */
- {
- FILE *fp;
- int i, x, y;
- int m;
- struct movelist *ml;
-
- if( type == REALMOVE ) {
- m = move;
- ml = realmovelist;
- }
- else if( type == STEPMOVE ) {
- m = currentmove;
- ml = stepmovelist;
- }
-
- if( (fp = fopen( (char *)s, "a+" )) == NULL ) {
- perror( "savegame" );
- return( 0 );
- }
-
- fprintf( fp, "\n%s\n", stamptime() );
- fprintf( fp, "White: %s\nBlack: %s\n", p1, p2 );
- fprintf( fp, "Handicap: %d\n\n", hcap );
-
- if( hcap != 0 ) {
- fprintf( fp, " 0 (B): Handicap %d\n", hcap );
- i = 1;
- }
- else i = 0;
-
- for( ; i <= m; ++i ) {
- x = ml[i].x + 1;
- y = ml[i].y + 1;
- fprintf( fp, "%3d (%c): ", i, (i%2) ? 'W' : 'B' );
- if( x < 0 ) fprintf( fp, "Pass\n" );
- else fprintf( fp, "%c%d\n", 'A' + ((x > 8) ? x + 1 : x) - 1, y );
- }
- fclose( fp );
- return( 1 );
- }
-
- boolean inRange( i, j )
- int i, j;
- {
- return i >= 0 && i < boardsize && j >= 0 && j < boardsize;
- }
-
- boolean alive0( b, m, i, j, t )
- boardtype b;
- boardtype m;
- int i, j;
- piece t;
- {
- piece pt;
-
- pt = b[i][j];
- if ((pt != EMPTY && pt != t) || m[i][j] != EMPTY) return 0;
- m[i][j] = (pt == t) ? (piece) 1 : (piece) 2;
- if (pt == EMPTY) return 1;
- return( j < boardsize - 1 && alive0(b, m, i, j + 1, t)) ||
- (i < boardsize - 1 && alive0(b, m, i + 1, j, t)) ||
- (i && alive0(b, m, i - 1, j, t)) ||
- (j && alive0(b, m, i, j - 1, t));
- }
-
- /* Does group at i,j have liberties? */
- boolean alive( b, i, j )
- boardtype b;
- int i, j;
- {
- boardtype m;
- int p[2];
-
- clearboard( m, p );
- return( alive0(b, m, i, j, b[i][j]) );
- }
-
-
- void removeStones0( b, pris, i, j, t )
- boardtype b;
- int *pris;
- int i, j;
- piece t;
- {
- if( b[i][j] != t ) return;
- b[i][j] = EMPTY;
-
- if( tt == REALMOVE ) {
- if( !boardchanged && !mouseflag ) {
- drawStone( i+1, j+1, EMPTY, TRUE );
- }
- }
- else if( tt == STEPMOVE ) {
- if( boardchanged || mouseflag ) {
- drawStone( i+1, j+1, EMPTY, TRUE );
- }
- }
-
- pris[t - 1]++;
- if( j < boardsize - 1 ) removeStones0( b, pris, i, j + 1, t );
- if( i < boardsize - 1 ) removeStones0( b, pris, i + 1, j, t );
- if( i ) removeStones0( b, pris, i - 1, j, t );
- if( j ) removeStones0( b, pris, i, j - 1, t );
- }
-
- void get_prisoners( x, y )
- int *x, *y;
- {
- *x = stepprisoners[0];
- *y = stepprisoners[1];
- }
-
- void set_prisoners( x, y )
- int x, y;
- {
- stepprisoners[0] = x;
- stepprisoners[1] = y;
- }
-
- void update_prisoners( x, y )
- int x, y;
- {
- stepprisoners[0] += x;
- stepprisoners[1] += y;
- }
-
- void score_it( i, j )
- int i, j;
- {
- --i;
- --j;
-
- tt = STEPMOVE;
- boardchanged = TRUE;
- removeStones( stepboard, stepprisoners, i, j );
- }
-
- void removeStones( b, pris, i, j )
- boardtype b;
- int *pris;
- int i, j;
- {
- removeStones0( b, pris, i, j, b[i][j] );
- }
-
- boolean tryKill( b, pris, i, j, t )
- boardtype b;
- int *pris;
- int i, j;
- piece t;
- {
- piece w;
-
- if (!inRange(i, j)) return false;
- w = b[i][j];
- if (w != EMPTY && w != t && !alive(b, i, j)) {
- removeStones(b, pris, i, j);
- return true;
- }
- else return false;
- }
-
- boolean placeStone( b, pris, i, j, t )
- boardtype b;
- int *pris;
- int i, j;
- piece t;
- {
- boolean ret = FALSE;
-
- if (inRange(i, j)) {
- b[i][j] = t;
- if (j) ret = tryKill(b, pris, i, j - 1, t);
- if (j < boardsize - 1) ret |= tryKill(b, pris, i, j + 1, t);
- if (i) ret |= tryKill(b, pris, i - 1, j, t);
- if (i < boardsize - 1) ret |= tryKill(b, pris, i + 1, j, t);
- }
- return( ret );
- }
-
- /* return the info on move "num" (real move) */
- getmove( num, x, y, f )
- int num;
- int *x, *y, *f;
- {
- *x = realmovelist[num].x+1;
- *y = realmovelist[num].y+1;
- *f = (int)realmovelist[num].flag;
- return( num );
- }
-
- /* delete the move "num" from the movetable */
- removemove( num, type )
- int num, type;
- {
- int x, y;
-
- if( type == REALMOVE ) {
- x = realmovelist[num].x;
- y = realmovelist[num].y;
- board[x][y] = EMPTY;
- realmovelist[num].x = 0;
- realmovelist[num].y = 0;
- realmovelist[num].flag = FALSE;
- }
- else if( type == STEPMOVE ) {
- x = stepmovelist[num].x;
- y = stepmovelist[num].y;
- stepboard[x][y] = EMPTY;
- stepmovelist[num].x = 0;
- stepmovelist[num].y = 0;
- stepmovelist[num].flag = FALSE;
- }
- }
-
- makemove( i, j, num, t, type )
- int i, j, num;
- piece t;
- int type; /* update REALMOVE, STEPMOVE data? */
- {
- int x, y, flag;
-
- tt = type;
-
- --i;
- --j;
- if( i < (-1) ) { /* pass */
- if( type == REALMOVE ) {
- realmovelist[num].x = i;
- realmovelist[num].y = j;
- realmovelist[num].flag = FALSE;
- }
- if( type == STEPMOVE ) {
- stepmovelist[num].x = i;
- stepmovelist[num].y = j;
- stepmovelist[num].flag = FALSE;
- }
- }
- else { /* place stone */
- if( type == REALMOVE ) {
- realmovelist[num].x = i;
- realmovelist[num].y = j;
- realmovelist[num].flag = placeStone( board, prisoners,
- i, j, t );
- }
- if( type == STEPMOVE ||
- (type == REALMOVE && (!boardchanged && !mouseflag)) ) {
- stepmovelist[num].x = i;
- stepmovelist[num].y = j;
- stepmovelist[num].flag = placeStone( stepboard,
- stepprisoners, i, j, t );
- }
- if( type == REALMOVE ) {
- if( !boardchanged && !mouseflag ) drawStone( i+1, j+1, t, TRUE);
- else beep();
- }
- if( type == STEPMOVE && (boardchanged || mouseflag) )
- drawStone( i+1, j+1, t, TRUE );
- }
- }
-
- static int verts[3][26] = {
- {0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 4},
- {0, 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 9, 0, 10, 0, 0, 0, 12},
- {0, 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 17, 0, 0, 0, 20},
- };
-
- /*
- * Set the handicap of "hand" stones on the board....
- * use "verts" table above....
- */
- sethandicap( hand, type )
- int hand;
- int type;
- {
- int top, mid, bot;
- piece t;
-
- top = verts[TOP][boardsize] +1;
- mid = verts[MID][boardsize] +1;
- bot = verts[BOT][boardsize] +1;
-
- /*
- * All of these drop through, '5' checks for odd points.
- */
- t=1;
- switch (hand) {
- case 9: /* taken care of by handi == 5 */
- case 8:
- makemove( mid, top, 0, t, type );
- makemove( mid, bot, 0, t, type );
- case 7: /* taken care of by handi == 5 */
- case 6:
- makemove( bot, mid, 0, t, type );
- makemove( top, mid, 0, t, type );
- case 5:
- /* odd points, test because of drop through */
- if (hand & 0x1) {
- makemove( mid, mid, 0, t, type );
- }
- case 4:
- makemove( bot, top, 0, t, type );
- case 3:
- makemove( top, bot, 0, t, type );
- case 2:
- makemove( bot, bot, 0, t, type );
- makemove( top, top, 0, t, type );
- break;
- default:
- break;
- }
- }
-
- sgf_hcap( f, s, h )
- FILE *f;
- int s, h;
- {
- char *ss = NULL;
-
- switch( s ) {
- case 19:
- switch( h ) {
- case 2:
- ss = "AddBlack[dp][pd]";
- break;
- case 3:
- ss = "AddBlack[dp][pd][dd]";
- break;
- case 4:
- ss = "AddBlack[dd][dp][pd][pp]";
- break;
- case 5:
- ss = "AddBlack[dd][dp][jj][pd][pp]";
- break;
- case 6:
- ss = "AddBlack[dd][dj][dp][pd][pj][pp]";
- break;
- case 7:
- ss = "AddBlack[dd][dj][dp][jj][pd][pj][pp]";
- break;
- case 8:
- ss = "AddBlack[dd][dj][dp][jd][jp][pd][pj][pp]";
- break;
- case 9:
- ss = "AddBlack[dd][dj][dp][jd][jj][jp][pd][pj][pp]";
- break;
- default:
- break;
- }
- break;
- case 13:
- switch( h ) {
- case 2:
- ss = "AddBlack[dj][jd]";
- break;
- case 3:
- ss = "AddBlack[dj][jd][dd]";
- break;
- case 4:
- ss = "AddBlack[dd][dj][jd][jj]";
- break;
- case 5:
- ss = "AddBlack[dd][dj][gg][jd][jj]";
- break;
- default:
- break;
- }
- break;
- case 9:
- switch( h ) {
- case 2:
- ss = "AddBlack[cg][gc]";
- break;
- case 3:
- ss = "AddBlack[cg][gc][cc]";
- break;
- case 4:
- ss = "AddBlack[cc][cg][gc][gg]";
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- if( ss != NULL ) fprintf( f, ";\n%s\n", ss );
- }
-